{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Wandering Drone"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "pixiedust": {
     "displayParams": {
      "aggregation": "SUM",
      "basemap": "light-v9",
      "handlerId": "mapView",
      "mapboxtoken": "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4M29iazA2Z2gycXA4N2pmbDZmangifQ.-g_vE53SD2WrJ6tFX7QHmA",
      "rowCount": "500",
      "title": "Drone"
     }
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">.pd_warning{display:none;}</style><div class=\"pd_warning\"><em>Hey, there's something awesome here! To see it, open this notebook outside GitHub, in a viewer like Jupyter</em></div>\n",
       "        <div class=\"pd_save is-viewer-good\" style=\"padding-right:10px;text-align: center;line-height:initial !important;font-size: xx-large;font-weight: 500;color: coral;\">\n",
       "            Drone\n",
       "        </div>\n",
       "    \n",
       "        <div id=\"chartFigure1624e60c\" class=\"pd_save\" style=\"overflow-x:auto\">\n",
       "            <script>\n",
       "  window.iframeLoaded = window.iframeLoaded || function(iframe) {\n",
       "    try {\n",
       "      iframe.contentWindow.pdMessageListeners = [];\n",
       "      iframe.contentWindow[\"addPDMessageListener\"] = function(listener){\n",
       "        iframe.contentWindow.pdMessageListeners.push(listener);\n",
       "      }\n",
       "      iframe.contentWindow.addEventListener(\"message\", function(event){\n",
       "        iframe.contentWindow.pdMessageListeners.forEach(function(listener){\n",
       "          listener(event);\n",
       "        });\n",
       "      }, false);\n",
       "      iframe.contentWindow.ready = true;\n",
       "      iframe.contentWindow[\"triggerPDEvent\"] = function(eventInfo) {\n",
       "        $(document).trigger('pd_event', eventInfo);\n",
       "      }\n",
       "    } catch (e) {\n",
       "      console.log(e)\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  !function(){\n",
       "    var comm_manager = Jupyter.notebook.kernel.comm_manager\n",
       "    var contentWindow = null\n",
       "    comm_manager.register_target(\"9271e29f-8098-40a5-81f0-9741762f057b\", function (comm, msg) {\n",
       "        return comm.on_msg(function(msg){\n",
       "            if (!contentWindow){\n",
       "              var n = $(\"#mapframe1624e60c\");\n",
       "              if (n.length>0){\n",
       "                contentWindow = n[0].contentWindow;\n",
       "              }else{\n",
       "                console.log(\"Unable to find contentWindow\");\n",
       "              }\n",
       "            }\n",
       "            if (contentWindow && contentWindow.ready){\n",
       "              contentWindow.postMessage(msg.content.data, \"*\");\n",
       "            }else{\n",
       "              var deferredData = msg.content.data;\n",
       "              var ival = setInterval(function(){\n",
       "                if (contentWindow && contentWindow.ready){\n",
       "                  contentWindow.postMessage(msg.content.data, \"*\");\n",
       "                  clearInterval(ival);\n",
       "                }\n",
       "              }, 1000 );\n",
       "            }\n",
       "        });\n",
       "    });\n",
       "  }();\n",
       "  \n",
       "</script>\n",
       "<iframe id=\"mapframe1624e60c\" style=\"width:878.4px;height:658.8px\" srcdoc=\"<!DOCTYPE html><html lang=&quot;en&quot;><head>    <meta charset=&quot;UTF-8&quot;>    <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;>    <title>Pixiedust Mapbox map</title>    <script src=&quot;https://api.tiles.mapbox.com/mapbox-gl-js/v0.32.1/mapbox-gl.js&quot;></script>    <link href=&quot;https://api.tiles.mapbox.com/mapbox-gl-js/v0.32.1/mapbox-gl.css&quot; rel=&quot;stylesheet&quot; />    <style>    .mapboxgl-popup-content h3 {         margin: 2px 0 2px 0;        font-style: italic;    }    .mapboxgl-popup {        max-width: 200px;    }    #map canvas {        cursor: crosshair;    }    .legend {        background-color: rgba(255,255,255, 0.75);        border-radius: 3px;        position: absolute;        left: calc(100% - 172px);        top: 14px;        box-shadow: 0 1px 2px rgba(0,0,0,0.10);        font-size: 12px;        line-height: 18px;        padding: 10px;        z-index: 1;    }    .legend h4 {        margin: 0 0 10px;    }    .legend div span {        border-radius: 50%;        display: inline-block;        height: 10px;        margin-right: 5px;        width: 10px;    }    body {         background-color:#333;         margin:0px !important;         overflow: hidden;        font-family: &quot;Helvetica Neue&quot;, Arial, Helvetica, sans-serif;    }    </style></head><body><div id=&quot;map-1624e60c-53d7d9ec&quot; style=&quot;width:calc(878.4px - 4px);height:calc(658.8px - 4px)&quot; ></div><script>    var comment = &quot;&quot;;    mapboxgl.accessToken=&quot;pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4M29iazA2Z2gycXA4N2pmbDZmangifQ.-g_vE53SD2WrJ6tFX7QHmA&quot;;    var map = new mapboxgl.Map({        container: &quot;map-1624e60c-53d7d9ec&quot;,        style: &quot;mapbox://styles/mapbox/light-v9&quot;    });    setTimeout(function(){        if (window.addPDMessageListener){            window.addPDMessageListener(function(event){                streamingLayer = map.getSource(&quot;streamingLayer&quot;);                if (streamingLayer){                    streamingLayer.setData(event.data.data);                }else{                    map.addLayer({                        &quot;id&quot;: &quot;streamingLayer&quot;,                        &quot;maptype&quot;: &quot;mapbox&quot;,                        &quot;type&quot;: event.data.type,                        &quot;source&quot;: { type: &quot;geojson&quot;, data: event.data.data },                        &quot;layout&quot;: event.data.layout || {},                        &quot;paint&quot;: event.data.paint || {}                    });                    if (event.data.fitbounds &amp;&amp; event.data.data.features){                        function updateBounds(res, ar){                            if (ar[0].length >=2 &amp;&amp; ar[1].length >= 2 ){                                if (!res){                                    return ar;                                }                                return [                                     [Math.min( ar[0][0]-0.1, res[0][0]), Math.min( ar[0][1]-0.1, res[0][1])],                                    [Math.max( ar[1][0]+0.1, res[1][0]), Math.max( ar[1][1]+0.1, res[1][1])]                                ]                            }                            return null;                        }                        var bbox = event.data.data.features.reduce(function(res, value){                            var coord = value.geometry.coordinates;                            if (coord.length >= 2 ){                                res = updateBounds( res, [coord[0], coord[1]]);                            }                            return res;                        }, null);                        if (bbox){                            map.fitBounds(bbox);                        }                    }                }            });        };    },100);    var popup = new mapboxgl.Popup({closeButton: false,closeOnClick: true});        map.on(&quot;mousemove&quot;, function (e) {        var fs = map.queryRenderedFeatures(e.point,{layers:[&quot;pxlayer&quot;]});        if (!fs || !fs.length) {popup.remove();return;};        popuphtml = &quot;&quot;;        var hr = false;        fs.forEach(function(f){            if (hr){                 popuphtml += &quot;<hr>\\n&quot;;            }            hr=true;            popuphtml += &quot;<h3>&quot;+f.layer.id.toUpperCase()+&quot;</h3>\\n&quot;;            var keylength = Object.keys(f.properties).length;            for (var key in f.properties) {                popuphtml += &quot;<b>&quot;+key+&quot;: </b> &quot;+f.properties[key]+&quot;<br/>\\n&quot;;            }        });        popup.setLngLat(e.lngLat).setHTML(popuphtml).addTo(map);    });        map.on(&quot;click&quot;, function (e) {        var fs = map.queryRenderedFeatures(e.point, { layers: [&quot;pxlayer&quot;] });        if (fs &amp;&amp; fs.length) {            var f = fs[0];            console.log(&quot;clicked&quot;, f);            var keylength = Object.keys(f.properties).length;            var payload = {type:&quot;select&quot;, targetDivId: &quot;&quot; };            for (var key in f.properties) {                payload[key] = f.properties[key];            }            if (window.triggerPDEvent) {                window.triggerPDEvent(payload);            }        }    });            map.on(&quot;load&quot;, function() {                comment = &quot;Add user layers&quot;;        var layers = [];                layers.sort(function(a,b) {            return a[1] - b[1];        });        for (layersi=layers.length-1; layersi>=0; layersi--) {            map.addLayer(layers[layersi][0]);            comment = &quot;User layer legend&quot;;                    }                    });</script></body></html>\" onload=\"iframeLoaded(this)\"></iframe>\n",
       "\n",
       "<div pd_refresh_rate=\"1000\">\n",
       "    <pd_script>\n",
       "from ipykernel.comm import Comm\n",
       "from pixiedust.display.streaming.streamingDisplay import *\n",
       "cellId = \"F9A4827DBA4249008E9858A8187557BA\"\n",
       "entity = activesStreamingEntities[cellId] if cellId in activesStreamingEntities else None\n",
       "if entity is not None:\n",
       "  comms = Comm(target_name=\"9271e29f-8098-40a5-81f0-9741762f057b\", data={}) if not hasattr(entity, \"comms\") else entity.comms\n",
       "  entity.comms = comms\n",
       "  metadata = entity.getMetadata();\n",
       "  comms.send({\n",
       "    \"data\": entity.getNextData(),\n",
       "    \"type\": metadata.get(\"type\", \"circle\"),\n",
       "    \"layout\": metadata.get(\"layout\", {}),\n",
       "    \"paint\": metadata.get(\"paint\", {}),\n",
       "    \"fitbounds\": metadata.get(\"fitbounds\", True)\n",
       "  })\n",
       "    <pd_script>\n",
       "</pd_script></pd_script></div>\n",
       "\n",
       "        </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pixiedust.display.streaming import *\n",
    "\n",
    "class DroneStreamingAdapter(StreamingDataAdapter):\n",
    "    def getMetadata(self):\n",
    "        iconImage = \"heliport-15\"\n",
    "        return {\n",
    "            \"layout\": {\"icon-image\": iconImage},\n",
    "            \"type\": \"symbol\"\n",
    "        }\n",
    "    def accept(self, handlerId):\n",
    "        return handlerId == 'mapView'\n",
    "    def doGetNextData(self):\n",
    "        return \"https://wanderdrone.appspot.com/\"\n",
    "   \n",
    "display(DroneStreamingAdapter())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "pySpark (Spark 1.6.0) Python 2",
   "language": "python",
   "name": "pyspark1.6python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
